/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package DAO;

import Search.solrSearch;
import common.GeneralHandling;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import pojo.Tag;
import org.apache.cassandra.thrift.*;
import org.apache.thrift.TException;
import pojo.Counter;
import pojo.Status;
/**
 *
 * @author tipuder
 */
public class TagDAO {
    private static Cassandra.Client client;
    private static TagDAO instance;   
    
    public static TagDAO getInstance(Cassandra.Client _client)
    {
        if (instance != null)
            return instance;
        instance = new TagDAO();
        client = _client;
        return instance;
    }
   
    //Insert một tag.
    public boolean insertTag(List<String> listnameTag)
    {
        boolean result = false;
        try {  
                for (String newTag : listnameTag)
                {
                    //Tạo supercolumn info_tag
                    SuperColumn info_tag = new SuperColumn();
                    info_tag.name = common.GeneralHandling.toByteBuffer(Tag.name_scol_info);
                    //String createD = Long.toString((new Date()).getTime());

                    info_tag.addToColumns(common.GeneralHandling.createCol(Tag.name_col_cdate, ""));

                    String modifyD = "";
                    info_tag.addToColumns(common.GeneralHandling.createCol(Tag.name_col_mdate, modifyD));

                    String state = "public";
                    info_tag.addToColumns(common.GeneralHandling.createCol(Tag.name_col_state, state));

                    //Insert supercolunm bằng batch_mutate
                    ByteBuffer rowkey = common.GeneralHandling.toByteBuffer(newTag);

                    List<Mutation> mutations = new ArrayList<Mutation>();

                    ColumnOrSuperColumn colorsupcol = new ColumnOrSuperColumn();
                    Mutation m = new Mutation();

                    colorsupcol.setSuper_column(info_tag);
                    m.setColumn_or_supercolumn(colorsupcol);
                    mutations.add(m);

                    Map<String, List<Mutation>> keyMutations = new HashMap<String, List<Mutation>>();
                    keyMutations.put(Tag.col_parent, mutations);

                    Map<ByteBuffer, Map<String, List<Mutation>>> mutationsMap = new HashMap<ByteBuffer, Map<String, List<Mutation>>>();
                    mutationsMap.put(rowkey, keyMutations);
                    client.batch_mutate(mutationsMap, common.Constants.CL);
                    
                }
                CounterDAO.Inscrease(Counter.colname_counter, client);
                result = true;
        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InvalidRequestException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnavailableException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TimedOutException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } 
        
        return result;
    }
    
    public boolean DeleteStatusIDInTag(String nameTag,String StatusID)
    {
        boolean result = false;
        try {
            
            ByteBuffer rowkey = common.GeneralHandling.toByteBuffer(nameTag);
            ColumnParent parent = new ColumnParent(Tag.col_parent);
            SlicePredicate predicate = new SlicePredicate();
            predicate.addToColumn_names(common.GeneralHandling.toByteBuffer(Tag.name_scol_lstatus));

            List<ColumnOrSuperColumn> col = client.get_slice(rowkey, parent, predicate, common.Constants.CL);
            SuperColumn sp = col.get(0).super_column;
//            SuperColumn newsp = new SuperColumn();
//            newsp.name = common.GeneralHandling.toByteBuffer(Tag.name_scol_lstatus);
//            for (Column c: sp.columns) {
//                String old_statusID = common.GeneralHandling.toString(c.name);
//                String name = common.GeneralHandling.toString(c.name);
//                String value = common.GeneralHandling.toString(c.value);
//                if (old_statusID.equals(StatusID))
//                    value = "1";
//                newsp.addToColumns(common.GeneralHandling.createCol(name,value));
//            }
            sp.addToColumns(common.GeneralHandling.createCol(StatusID, "1"));
            //sp.addToColumns(common.GeneralHandling.createCol("", ""));
            addSuperColumn(sp, rowkey);
            predicate = new SlicePredicate();
            predicate.addToColumn_names(common.GeneralHandling.toByteBuffer((Tag.name_scol_info)));
            col = client.get_slice(rowkey, parent, predicate, common.Constants.CL);
            sp = col.get(0).super_column;
            sp.addToColumns(common.GeneralHandling.createCol(Tag.name_col_mdate,""));
            addSuperColumn(sp, rowkey);

            result = true; 
           
        } catch (InvalidRequestException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnavailableException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TimedOutException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } 
        
        return result;
    }
    
    public boolean deleteTag(List<String> listNameTag)
    {
        boolean result = false;
        
        for (String nameTag : listNameTag) {
            try {
                ByteBuffer rowkey = common.GeneralHandling.toByteBuffer(nameTag);
                SlicePredicate predicate = new SlicePredicate();
                predicate.addToColumn_names(common.GeneralHandling.toByteBuffer(Tag.name_scol_lstatus));
                ColumnParent parent = new ColumnParent(Tag.col_parent);
                
                //Lay danh sach status trong Tag de cap nhat lai.
                List<ColumnOrSuperColumn> temp = client.get_slice(rowkey, parent, predicate, common.Constants.CL);
                SuperColumn supercol = temp.get(0).super_column;
                List<ByteBuffer> liststatusID = new ArrayList<ByteBuffer>();
                for(Column col : supercol.columns)
                    liststatusID.add(col.name);
                
                //Remove Tag hien hanh
                ColumnPath path = new ColumnPath(Tag.col_parent);
                client.remove(rowkey, path, System.currentTimeMillis(), common.Constants.CL);
                
                //Goi phuong thuc UpdatelistTag de loai bo tag trong status tuong ung.
                StatusDAO staDAO = StatusDAO.getInstance(client);
                staDAO.UpdatelistTag(liststatusID, nameTag);
                CounterDAO.Decrease(Counter.colname_counter, client);
                result = true;
                
            } catch (UnsupportedEncodingException ex) {
                Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
            } catch (InvalidRequestException ex) {
                Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
            } catch (UnavailableException ex) {
                Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
            } catch (TimedOutException ex) {
                Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
            } catch (TException ex) {
                Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        
        return result;
    }
    
    private void addSuperColumn(SuperColumn sp, ByteBuffer rowkey)
    {
        try {
            List<Mutation> mutations = new ArrayList<Mutation>();

            ColumnOrSuperColumn colorsupcol = new ColumnOrSuperColumn();
            Mutation m = new Mutation();

            colorsupcol.setSuper_column(sp);
            m.setColumn_or_supercolumn(colorsupcol);
            mutations.add(m);

            Map<String, List<Mutation>> keyMutations = new HashMap<String, List<Mutation>>();
            keyMutations.put(Tag.col_parent, mutations);

            Map<ByteBuffer, Map<String, List<Mutation>>> mutationsMap = new HashMap<ByteBuffer, Map<String, List<Mutation>>>();
            mutationsMap.put(rowkey, keyMutations);
            client.batch_mutate(mutationsMap, common.Constants.CL);

        } catch (InvalidRequestException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnavailableException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TimedOutException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    public boolean InsertStatusIDToTag(String StatusID,String nameTag)
    {
        boolean result = false;
        try {
            
            Tag updateTag = selectTagFromID(nameTag);
            SuperColumn liststatus = new SuperColumn();
            liststatus.name = common.GeneralHandling.toByteBuffer(Tag.name_scol_lstatus);
            
            List<String> lstatus = updateTag.getList_status_ID();
            if (lstatus == null)// Tag chưa có statusID nào.
                lstatus = new ArrayList<String>();
            lstatus.add(StatusID);
            for (int i = 0; i < lstatus.size(); i++)
            {
                String colname = lstatus.get(i);
                liststatus.addToColumns(common.GeneralHandling.createCol(colname, ""));
            }
            
            ByteBuffer rowkey = common.GeneralHandling.toByteBuffer(updateTag.getName_tag());
                
            List<Mutation> mutations = new ArrayList<Mutation>();

            ColumnOrSuperColumn colorsupcol = new ColumnOrSuperColumn();
            Mutation m = new Mutation();
            
            colorsupcol.setSuper_column(liststatus);
            m.setColumn_or_supercolumn(colorsupcol);
            mutations.add(m);

            Map<String, List<Mutation>> keyMutations = new HashMap<String, List<Mutation>>();
            keyMutations.put(Tag.col_parent, mutations);

            Map<ByteBuffer, Map<String, List<Mutation>>> mutationsMap = new HashMap<ByteBuffer, Map<String, List<Mutation>>>();
            mutationsMap.put(rowkey, keyMutations);
            client.batch_mutate(mutationsMap, common.Constants.CL);
                   
            result = true;
           
        } catch (InvalidRequestException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnavailableException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TimedOutException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        return result;
        
    }

    public boolean updateStateTag(List<String> listTagName, String newState)
    {
        boolean result = false;
        try {
                for(String tagName : listTagName){
                SuperColumn infoTag = new SuperColumn();
                infoTag.name = common.GeneralHandling.toByteBuffer(Tag.name_scol_info);
                Tag tag = selectTagFromID(tagName);
                
                ByteBuffer rowkey = common.GeneralHandling.toByteBuffer(tagName);
                infoTag.addToColumns(common.GeneralHandling.createCol(Tag.name_col_cdate, tag.getCreate_date()));
                infoTag.addToColumns(common.GeneralHandling.createCol(Tag.name_col_mdate, ""));
                infoTag.addToColumns(common.GeneralHandling.createCol(Tag.name_col_state, newState));
                List<Mutation> mutations = new ArrayList<Mutation>();

                ColumnOrSuperColumn colorsupcol = new ColumnOrSuperColumn();
                Mutation m = new Mutation();

                colorsupcol.setSuper_column(infoTag);
                m.setColumn_or_supercolumn(colorsupcol);
                mutations.add(m);

                Map<String, List<Mutation>> keyMutations = new HashMap<String, List<Mutation>>();
                keyMutations.put(Tag.col_parent, mutations);

                Map<ByteBuffer, Map<String, List<Mutation>>> mutationsMap = new HashMap<ByteBuffer, Map<String, List<Mutation>>>();
                mutationsMap.put(rowkey, keyMutations);
                client.batch_mutate(mutationsMap, common.Constants.CL);
            }
            result = true;
           
        } catch (InvalidRequestException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnavailableException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TimedOutException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        return result;
        
    }    
    
    public Tag selectTagFromID(String nameTag)
    {
        Tag result = new Tag();
        
        try {
        
            SlicePredicate predicate = new SlicePredicate();
            SliceRange range = new SliceRange(GeneralHandling.toByteBuffer(""), GeneralHandling.toByteBuffer(""), false, 10);
            predicate.setSlice_range(range);

            ColumnParent parent = new ColumnParent(Tag.col_parent);

            List<ColumnOrSuperColumn> results = client.get_slice(GeneralHandling.toByteBuffer(nameTag), parent, predicate, common.Constants.CL);

            if (!results.isEmpty())
            {
                result.setName_tag(nameTag);
                for (ColumnOrSuperColumn temp : results)
                {
                    SuperColumn sc = temp.super_column;
                    String colname = common.GeneralHandling.toString(sc.name);
                    if (Tag.name_scol_lstatus.equals(colname))
                    {
                        List<String> list_status_ID = new ArrayList<String>();
                        for (Column col : sc.columns)
                            list_status_ID.add(common.GeneralHandling.toString(col.name));
                        result.setList_status_ID(list_status_ID);
                    }
                    else
                        for (Column col : sc.columns)
                        {
                            String name = common.GeneralHandling.toString(col.name);
                            String value = common.GeneralHandling.toString(col.value);
                            switch (name.charAt(0))
                            {
                                case 'c':
                                {
                                    result.setCreate_date(value);
                                }
                                case 'm':
                                {
                                    result.setModify_date(value);
                                }
                                case 's':
                                {
                                    result.setState(value);
                                }
                            }
                        }
                    }
                }
        } catch (TException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InvalidRequestException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnavailableException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TimedOutException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        }
        return result;
    }
    
    public String PrintALLTag()
    {
        String result = "{\"result\":[";
        try {
            List<ByteBuffer> colNames = new ArrayList<ByteBuffer>();
            colNames.add(common.GeneralHandling.toByteBuffer(Tag.name_scol_info));
            SlicePredicate predicate = new SlicePredicate();
            predicate.column_names = colNames;
            
            ColumnParent parent = new ColumnParent(Tag.col_parent); 
            KeyRange range = new KeyRange();
            range.start_key = common.GeneralHandling.toByteBuffer("");
            range.end_key = common.GeneralHandling.toByteBuffer("");
            
            List<KeySlice> results = client.get_range_slices(parent, predicate, range, common.Constants.CL);
            for (KeySlice row : results)
            {
                Tag temp = selectTagFromID(common.GeneralHandling.toString(row.key));
                if (temp.getName_tag() != null && temp.getList_status_ID() != null /*&& "public".equals(temp.getState())*/)
                    result += ParseToJSON(temp);
            }
            result = result.substring(0, result.length()-1);
            result += "]}";
        } catch (TException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InvalidRequestException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnavailableException ex) {
            return "{}";
        } catch (TimedOutException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(TagDAO.class.getName()).log(Level.SEVERE, null, ex);
        }
        return result;
    }
    
    public String searchTags(String value, String start, String end, String filter) throws Exception
    {
        String result = "{\"result\":[";
        int _start = Integer.parseInt(start);
        int _end = Integer.parseInt(end);
        int _filter = Integer.parseInt(filter);
        ArrayList<String[]> list = (new solrSearch()).searchTags(value, _start, _end, _filter);
        
        for (String[] temp : list) {
            Tag newTag = new Tag();
            newTag.setName_tag(temp[1]);
            newTag.setCreate_date(temp[2]);
            newTag.setModify_date(temp[3]);
            newTag.setState(temp[4]);
            newTag.setList_status_ID(null);
            result += ParseToJSON(newTag);
        }
        result = result.substring(0, result.length()-1);
        result += "]}";
        return result;
    }
    
    private String ParseToJSON(Tag temp)
    {
        String result = "";
        result += "{\"NameTag\":\"" + temp.getName_tag() + "\",";
        result += "\""+ Tag.name_scol_lstatus +"\":[";
        if (temp.getList_status_ID() != null)
        {
            List<String> list = temp.getList_status_ID();
            for (int i = 0; i < list.size(); i++) {
                String x = list.get(i);
                result += "\"" + x + "\",";
            }
            result = result.substring(0, result.length()-1);
        }
        
        result += "],\"" + Tag.name_col_cdate + "\":\"" + temp.getCreate_date() + "\",";
        result += "\"" + Tag.name_col_mdate + "\":\"" + temp.getModify_date() + "\",";
        result += "\"" + Tag.name_col_state + "\":\"" + temp.getState() + "\"";
        result += "},";
        return result;
    }
}
